package com.lry.basic.juc;


import com.alibaba.excel.annotation.ExcelProperty;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.atomic.LongAdder;

public class MyCasLock {


    Thread t;

    LongAdder reentry = new LongAdder();

    volatile int state;

    @ExcelProperty
    private static final Unsafe UNSAFE;

    private static final long stateOffset;
    static {
        try {
            UNSAFE = getUnsafeInstance();
            Class<?> ak = MyCasLock.class;
            stateOffset = UNSAFE.objectFieldOffset
                    (ak.getDeclaredField("state"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    //使用方法
    private static Unsafe getUnsafeInstance() throws Exception{
        Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeInstance.setAccessible(true);
        return (Unsafe) theUnsafeInstance.get(Unsafe.class);
    }



    public void lock(){
        //抢锁成功
        if(t==Thread.currentThread()){
            reentry.increment();
            return;
        }

        //修改不成功代表枪锁失败，一直自旋
        while(!UNSAFE.compareAndSwapInt(this,stateOffset,0,1)){

        }
        //抢锁成功
        reentry.increment();
        t = Thread.currentThread();
    }

    public void unLock(){
        while(!UNSAFE.compareAndSwapInt(this,stateOffset,1,0)){

        }
        //释放锁成功
        reentry.decrement();
        if(reentry.intValue()==0)
            t = null;
    }

}

class TestMyCasLock{
    MyCasLock casLock = new MyCasLock();

    public static void main(String[] args) {
        TestMyCasLock testMyCasLock = new TestMyCasLock();

        new Thread(()->{
            testMyCasLock.add();
            testMyCasLock.add();
        }).start();

        new Thread(()->{
            testMyCasLock.add();

        }).start();
    }


    public void add(){
        try{
            System.out.println(Thread.currentThread().getName()+"抢锁中......");
            casLock.lock();
            System.out.println(Thread.currentThread().getName()+"抢锁成功");
        }  finally {
            casLock.unLock();
            System.out.println(Thread.currentThread().getName()+"释放锁成功");
        }
    }

}


